use axum::{
    extract::{Extension, Path, Query},
    Json,
};
use serde::{Deserialize, Serialize};

use sqlx::{MySql, Pool};

use crate::utils::empty_string_as_none;
use crate::{jwt::Claims, res::Res, utils::check_admin};

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct CreateOrder {
    menu_id: i32,
    phone: Option<String>,
    username: Option<String>,
    address: Option<String>,
}

pub async fn create_order(
    claims: Claims,
    body: Json<CreateOrder>,
    Extension(pool): Extension<Pool<MySql>>,
) -> Res<u64> {
    let mut res = Res::default();

    // 从token中获取用户编号
    let user_id: i32 = claims.sub.parse().unwrap();

    log::debug!("{:#?}", body);

    // 套餐编号
    let menu_id = body.menu_id;

    // 根据套餐编号查询出套餐信息
    let menu = match sqlx::query!("SELECT * FROM menus WHERE id = ?", menu_id)
        .fetch_one(&pool)
        .await
    {
        Ok(v) => v,
        Err(e) => {
            log::error!("获取套餐信息出错:{},id:{}", e, menu_id);
            res.set_code(-5);
            res.set_msg("获取套餐信息出错");
            return res;
        }
    };

    // 创建订单
    let id = match sqlx::query!(
        r#"insert into 
        orders(
           user_id,username, menu_id, name,pic, price, address, phone
        ) 
        values(?,?,?,?,?,?,?,?)"#,
        user_id,
        &body.username,
        menu_id,
        &menu.name,
        &menu.pic,
        &menu.price,
        &body.address,
        &body.phone,
    )
    .execute(&pool)
    .await
    {
        Ok(v) => {
            // 插入后的用户编号
            v.last_insert_id()
        }
        Err(e) => {
            log::error!("预约出错:{}", e);
            res.set_code(-2);
            res.set_msg("服务端出错，请联系管理");
            return res;
        }
    };

    // 更新用户表中的用户名
    if body.username.is_some() {
        if let Err(e) = sqlx::query!(
            "update users set name=? where id=?",
            &body.username,
            user_id
        )
        .execute(&pool)
        .await
        {
            log::error!("修改用户姓名出错:{}", e);
            res.set_code(-20);
            res.set_msg("服务端出错，请联系管理");
            return res;
        }
    }

    res.set_data(id);
    res
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct ListOrder {
    id: i32,
    user_id: i32,
    menu_id: i32,
    phone: String,
    name: String,
    username: Option<String>,
    address: String,
    price: i32,
    pic: String,
    count: Option<i32>,
    status: Option<i8>,
    created_at: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct Status {
    #[serde(default, deserialize_with = "empty_string_as_none")]
    status: Option<i32>,
}

/// 订单列表
pub async fn get_orders(
    claims: Claims,
    Extension(pool): Extension<Pool<MySql>>,
    Query(status): Query<Status>,
) -> Res<Vec<ListOrder>> {
    let mut res = Res::default();

    log::debug!("status:{:?}", status);

    // 从token中获取用户编号
    let user_id: i32 = claims.sub.parse().unwrap();

    let mut reservations = vec![];

    let is_admin = check_admin(user_id, &pool).await;

    if is_admin {
        let rs = match sqlx::query!("SELECT * FROM orders  order by created_at desc")
            .fetch_all(&pool)
            .await
        {
            Ok(v) => v,
            Err(e) => {
                log::error!("获取订单列表出错:{}", e);
                res.set_code(-1);
                res.set_msg("获取订单列表出错");
                return res;
            }
        };

        for v in rs {
            reservations.push(ListOrder {
                id: v.id,
                user_id: v.user_id,
                phone: v.phone,
                name: v.name,
                username: v.username,
                address: v.address,
                status: v.status,
                created_at: match v.created_at {
                    Some(v) => Some(v.to_string()),
                    None => None,
                },
                menu_id: v.menu_id,
                price: v.price,
                pic: v.pic,
                count: v.count,
            });
        }
    } else {
        let rs = match sqlx::query!(
            "SELECT * FROM orders where user_id=?  order by created_at desc",
            user_id
        )
        .fetch_all(&pool)
        .await
        {
            Ok(v) => v,
            Err(e) => {
                log::error!("获取订单列表出错:{}", e);
                res.set_code(-1);
                res.set_msg("获取订单列表出错");
                return res;
            }
        };

        for v in rs {
            reservations.push(ListOrder {
                id: v.id,
                user_id: v.user_id,
                phone: v.phone,
                name: v.name,
                username: v.username,
                address: v.address,
                status: v.status,
                created_at: match v.created_at {
                    Some(v) => Some(v.to_string()),
                    None => None,
                },
                menu_id: v.menu_id,
                price: v.price,
                pic: v.pic,
                count: v.count,
            });
        }
    }

    res.set_data(reservations);

    res
}

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct EditOrder {
    status: Option<i8>,
}

pub async fn edit_order(
    claims: Claims,
    Path(id): Path<i32>,
    rs: Json<EditOrder>,
    Extension(pool): Extension<Pool<MySql>>,
) -> Res<u64> {
    let mut res = Res::default();

    // 从token中获取用户编号
    let user_id: i32 = claims.sub.parse().unwrap();

    // 管理员才可以编辑订单
    let is_admin = check_admin(user_id, &pool).await;
    if !is_admin {
        res.set_code(-10);
        res.set_msg("只有管理员可以编辑订单");
        return res;
    }

    let rows_affected = match sqlx::query!(
        r#"update orders
           set status=?
           where id=?"#,
        &rs.status,
        id,
    )
    .execute(&pool)
    .await
    {
        Ok(v) => {
            // 受影响的行数
            v.rows_affected()
        }
        Err(e) => {
            log::error!("编辑订单出错:{}", e);
            res.set_code(-2);
            res.set_msg("服务端出错，请联系管理");
            return res;
        }
    };

    res.set_data(rows_affected);

    res
}

pub async fn delete_order(
    claims: Claims,
    Path(id): Path<i32>,
    Extension(pool): Extension<Pool<MySql>>,
) -> Res<u64> {
    let mut res = Res::default();

    // 从token中获取用户编号
    let user_id: i32 = claims.sub.parse().unwrap();

    let is_admin = check_admin(user_id, &pool).await;
    if !is_admin {
        res.set_code(-10);
        res.set_msg("只有管理员可以删除订单");
        return res;
    }

    log::debug!("id:{}", id);
    let rows_affected = match sqlx::query!("delete from orders where id=?", id)
        .execute(&pool)
        .await
    {
        Ok(v) => v.rows_affected(),
        Err(e) => {
            log::error!("删除厨师出错:{}", e);
            res.set_code(-1);
            res.set_msg("删除厨师出错");
            return res;
        }
    };
    res.set_data(rows_affected);
    res
}
